/**
 * Copyright (C) 2010 David Simonek <dafesimonek@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.dafe.partyband.gui.concerts;

import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PrinterException;
import java.util.Collection;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import org.dafe.partyband.db.api.IConcert;
import org.dafe.partyband.db.api.ISong;
import org.dafe.partyband.db.api.handlers.IConcertHandler;
import org.dafe.partyband.db.api.DbManager;
import org.dafe.partyband.gui.exports.ExportWizardAction;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.Exceptions;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.Lookup.Result;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;


/**
 *
 * @author dafe
 */
public class ConcertActionsFactory {

    private static final IConcertHandler handler = DbManager.getBandManager().getHandlersLookup().lookup(IConcertHandler.class);

    public static Action createMoveSongAction(String name, String tooltip, IConcert concert, PlaylistPanel playlistPanel, Lookup selSongLkp, int indexDelta) {
        return new MoveSongAction(name, tooltip, concert, selSongLkp, playlistPanel, indexDelta);
    }

    public static Action createDeleteSongAction(IConcert concert, PlaylistPanel playlistPanel, Lookup selSongLkp) {
        return new DeleteSongAction(concert, playlistPanel, selSongLkp);
    }

    public static Action createAddAction(IConcert concert, PlaylistPanel playlistPanel) {
        return new AddAction(concert, playlistPanel);
    }

    public static Action createPrintPlaylistAction(IConcert concert, PlaylistPanel playlistPanel) {
        return new PrintPlaylistAction(concert, playlistPanel);
    }
    
    public static Action createExportSongAction(Lookup selSongLkp) {
        return new ExportWizardAction(NbBundle.getMessage(ConcertActionsFactory.class, "ACT_ExportSongs"), selSongLkp);
    }
    

    private static class AddAction extends AbstractAction {
        private final IConcert concert;
        private final PlaylistPanel playlistPanel;

        public AddAction(IConcert concert, PlaylistPanel playlistPanel) {
            super(NbBundle.getMessage(ConcertActionsFactory.class, "ACT_Add2Concert"));
            this.concert = concert;
            this.playlistPanel = playlistPanel;
        }

        public void actionPerformed(ActionEvent e) {
            final AddSongsPanel panel = new AddSongsPanel();
            final JButton addButton = new JButton(
                    NbBundle.getMessage(ConcertActionsFactory.class, "AddSongsPanel.addButton"));
            final JButton closeButton = new JButton(
                    NbBundle.getMessage(ConcertActionsFactory.class, "AddSongsPanel.closeButton"));

            class ButtonListener implements ActionListener {
                private DialogDescriptor dd;
                public void actionPerformed(ActionEvent e) {
                    if (dd.getValue() == addButton) {
                        List<? extends ISong> selSongs = panel.getSelectedSongs();
                        for (ISong song : selSongs) {
                            handler.addSong(concert, song);
                        }
                        playlistPanel.refresh();
                        panel.clearSearchText();
                    }
                }
                void attachDescriptor (DialogDescriptor dd) {
                    this.dd = dd;
                }
            } // end of ButtonListener

            ButtonListener btnListener = new ButtonListener();

            final DialogDescriptor dd = new DialogDescriptor(
                    panel,
                    NbBundle.getMessage(CreateConcertAction.class, "TIT_Add2Concert"),
                    false,
                    new Object[] { addButton, closeButton },
                    addButton,
                    DialogDescriptor.DEFAULT_ALIGN,
                    HelpCtx.DEFAULT_HELP,
                    btnListener
            );
            dd.setClosingOptions(new Object[] { closeButton });
            panel.attachAddButton(addButton);
            btnListener.attachDescriptor(dd);
            Dialog dlg = DialogDisplayer.getDefault().createDialog(dd);
            dlg.setVisible(true);
        }
    }

    private static class DeleteSongAction extends AbstractAction implements LookupListener {
        private final IConcert concert;
        private final Result<ISong> selSongResult;
        private final PlaylistPanel playlistPanel;

        public DeleteSongAction(IConcert concert, PlaylistPanel playlistPanel, Lookup selSongLkp) {
            super(NbBundle.getMessage(ConcertActionsFactory.class, "ACT_DeleteSong"));
            putValue(Action.SHORT_DESCRIPTION, NbBundle.getMessage(
                    ConcertActionsFactory.class, "HINT_DeleteSong"));
            this.concert = concert;
            this.playlistPanel = playlistPanel;
            this.selSongResult = selSongLkp.lookupResult(ISong.class);
            this.selSongResult.addLookupListener(this);

            updateEnabled();
        }

        public void actionPerformed(ActionEvent e) {
            Collection<? extends ISong> songs = selSongResult.allInstances();
            int index = -1;
            for (ISong curSong : songs) {
                if (index < 0) {
                    index = concert.getSongs().indexOf(curSong);
                }
                handler.removeSong(concert, curSong);
            }
            playlistPanel.refresh();
            final int songCount = concert.getSongs().size();
            if (songCount > 0) {
                playlistPanel.setSelectedIndex(Math.min(index, songCount - 1));
            }
        }

        private void updateEnabled() {
            setEnabled(selSongResult.allInstances().size() > 0);
        }

        public void resultChanged(LookupEvent ev) {
            updateEnabled();
        }

    }

    private static class MoveSongAction extends AbstractAction implements LookupListener {
        private final IConcert concert;
        private final Result<ISong> selSongResult;
        private final int indexDelta;
        private final PlaylistPanel playlistPanel;

        public MoveSongAction(String name, String tooltip, IConcert concert, Lookup selSongLkp, PlaylistPanel playlistPanel, int indexDelta) {
            super(name);
            putValue(Action.SHORT_DESCRIPTION, tooltip);
            this.concert = concert;
            this.indexDelta = indexDelta;
            this.playlistPanel = playlistPanel;
            this.selSongResult = selSongLkp.lookupResult(ISong.class);
            this.selSongResult.addLookupListener(this);
            
            updateEnabled();
        }

        public void actionPerformed(ActionEvent e) {
            ISong song = ((List<? extends ISong>) selSongResult.allInstances()).get(0);
            int newIndex = concert.getSongs().indexOf(song) + indexDelta;
            handler.removeSong(concert, song);
            handler.addSong(concert, song, newIndex);
            playlistPanel.refresh();
            playlistPanel.setSelectedIndex(newIndex);
        }

        private void updateEnabled() {
            List<? extends ISong> selSongs = (List<? extends ISong>) selSongResult.allInstances();
            if (selSongs.size() != 1) {
                setEnabled(false);
            } else {
                ISong selSong = selSongs.get(0);
                List<? extends ISong> concertSongs = concert.getSongs();
                int newIndex = concertSongs.indexOf(selSong) + indexDelta;
                setEnabled(newIndex >= 0 && newIndex <= concertSongs.size() - 1);
            }

        }

        public void resultChanged(LookupEvent ev) {
            updateEnabled();
        }

    }

    private static class PrintPlaylistAction extends AbstractAction {
        private final IConcert concert;
        private final PlaylistPanel playlistPanel;

        public PrintPlaylistAction(IConcert concert, PlaylistPanel playlistPanel) {
            super(NbBundle.getMessage(ConcertActionsFactory.class, "ACT_PrintPlaylist"));
            putValue(Action.SHORT_DESCRIPTION, NbBundle.getMessage(
                    ConcertActionsFactory.class, "HINT_PrintPlaylist"));
            this.concert = concert;
            this.playlistPanel = playlistPanel;
        }

        public void actionPerformed(ActionEvent e) {
            try {
                playlistPanel.getPlaylistTable().print();
            } catch (PrinterException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

}
